package ws.performancetest.tests.jdbcdriver.runnable;

import java.sql.Date;
import java.util.concurrent.atomic.AtomicInteger;
import ws.jdbc.concurrent.driver.sqlserver.CStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import ws.jdbc.concurrent.driver.sqlserver.cursor.wrapper.CursorFactoryImpl;
import ws.jdbc.concurrent.driver.sqlserver.cursor.wrapper.ICursorFactory;

/**
 *
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public abstract class ResultSetRunnable extends Thread {

  protected static Connection con;
  protected static String sqlQuery;
  protected static CStatement stmt;
  protected static ICursorFactory factory;
  protected static int fetchSize;
  protected static int rsType = ResultSet.TYPE_SCROLL_SENSITIVE;
  protected static int rsConcur = ResultSet.CONCUR_READ_ONLY;
  protected static int cycleCount;
  protected static int linesPerThread;
  protected static AtomicInteger counter = new AtomicInteger();
  protected ResultSet rs;
  protected int val1;
  protected String val2;
  protected String val3;
  protected Date val4;
  protected Double val5;
  protected int val6;
  protected Date val7;
  protected String val8;

  protected final void initUpdateValues() {
    int n = (int) Thread.currentThread().getId();
    val2 = "StdF " + n;
    val3 = "StdL " + n;
    val4 = new java.sql.Date(n);
    val5 = 10.0;
    val6 = n;
    val7 = new java.sql.Date(n);
    val8 = n + "@mail.com";
  }

  private static void setup(Connection con, String sqlQuery, int rsType, int rsConcur, int fetchSize, int cycleCount) throws SQLException {
    ResultSetRunnable.con = con;
    ResultSetRunnable.sqlQuery = sqlQuery;
    ResultSetRunnable.rsType = rsType;
    ResultSetRunnable.rsConcur = rsConcur;
    ResultSetRunnable.fetchSize = fetchSize;
    ResultSetRunnable.linesPerThread = cycleCount;
    ResultSetRunnable.counter.set(1);
  }

  public static void setupJDBC(Connection con, String sqlQuery, int rsType, int rsConcur, int fetchSize, int cycleCount) throws SQLException {
    ResultSetRunnable.setup(con, sqlQuery, rsType, rsConcur, fetchSize, cycleCount);
  }

  public static void setupCJDBCI(Connection con, String sqlQuery, int rsType, int rsConcur, int fetchSize, int cycleCount) throws SQLException {
    ResultSetRunnable.setup(con, sqlQuery, rsType, rsConcur, fetchSize, cycleCount);

    stmt = (CStatement) con.createStatement(rsType, rsConcur);
    stmt.setFetchSize(fetchSize);
    stmt.setShared(false);
    stmt.executeQuery(sqlQuery);
  }

  public static void setupCJDBCS(Connection con, String sqlQuery, int rsType, int rsConcur, int cycleCount) throws SQLException {
    ResultSetRunnable.setup(con, sqlQuery, rsType, rsConcur, 0, cycleCount);

    stmt = (CStatement) con.createStatement(rsType, rsConcur);
    stmt.setFetchSize(0);
    stmt.executeQuery(sqlQuery);
  }

  /**
   * This is a special setup for CDJBC with shared cache. It is supposed to be
   * used on the test that compares the version with shared cache against the
   * version with individual cache.
   *
   * @param con
   * @param sqlQuery
   * @param rsType
   * @param rsConcur
   * @param fetchSize
   * @param cycleCount
   * @param numberOfThreads
   * @throws SQLException
   */
  public static void setupCJDBCS(Connection con, String sqlQuery, int rsType, int rsConcur, int fetchSize, int cycleCount) throws SQLException {
    ResultSetRunnable.setup(con, sqlQuery, rsType, rsConcur, fetchSize, cycleCount);

    stmt = (CStatement) con.createStatement(rsType, rsConcur);
    stmt.setFetchSize(fetchSize);
    stmt.setShared(true);
    stmt.executeQuery(sqlQuery);
  }

  public static void setupWJDBC(Connection con, String sqlQuery, int rsType, int rsConcur, int fetchSize, int cycleCount) throws SQLException {
    ResultSetRunnable.setup(con, sqlQuery, rsType, rsConcur, fetchSize, cycleCount);

    Statement st = con.createStatement(rsType, rsConcur);
    st.setFetchSize(fetchSize);
    factory = new CursorFactoryImpl(st.executeQuery(sqlQuery));
  }
  
  private static int delayms = 0;

  public static void setDelay(int delayms) {
    ResultSetRunnable.delayms = delayms;
  }

  public static float getDelay() {
    return delayms;
  }

  public static double calc;

  static final Object obj = new Object();
  public static void delayfunc() {
    try{
      synchronized(obj) {
        obj.wait(delayms);
      } 
    }catch(InterruptedException ex) {
    }
  }
}
